package com.example.ecmftlutil.util.pdf;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ClassUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;

public class TemplateUtil {

    private static Configuration freemarkerCfgOut = null;
    private static Configuration freemarkerCfg = null;

    private static final Logger logger = LoggerFactory.getLogger(TemplateUtil.class);
    private static final String FONT = "font/simsun.ttf";
    private static String pathPrefix = File.separator + "templates" + File.separator;
    private static final File folder = new File("./template");
    public static final String COVER_DPF_TEMPLATE = "file_cover_template.ftl";
    public static final String GENERAL_COVER_DPF_TEMPLATE = "general_file_cover_template.ftl";
    public static final String VOUCHER_TEMPLATE = "voucher_template_new.ftl";
    public static Resource[] fonts=null;

    //分别配置template在项目内、外两种情况
    /*static {
        freemarkerCfgOut = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        freemarkerCfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        try{
            //freemarker的模板目录(项目外部)
            logger.info("templatePath outside is [{}]. ", folder);
            if (folder.exists()) {
                freemarkerCfgOut.setDirectoryForTemplateLoading(folder);
                freemarkerCfgOut.setClassicCompatible(true);
            }


            //freemarker的模板目录(项目内部)
            pathPrefix = File.separator + "templates" + File.separator;
            // 为了支持能从execute jar 中获取模板文件
            URI uri = ClassUtils.getDefaultClassLoader().getResource("templates").toURI();
            logger.info("uri is [{}], uri scheme is [{}]. ", uri, uri.getScheme());
            if (uri.getScheme().equals("jar")) {
                pathPrefix = File.separator + "BOOT-INF" + File.separator + "classes" + File.separator + "templates" + File.separator;
            }
            logger.info("pathPrefix is [{}]. ", pathPrefix);
            freemarkerCfg.setClassForTemplateLoading(TemplateUtil.class, pathPrefix);
            freemarkerCfg.setClassicCompatible(true);
            //获取所有字体文件
            fonts = new PathMatchingResourcePatternResolver().getResources("font/*.ttf");

        } catch (Exception e) {
            logger.error("", e);
        }
    }*/

    private TemplateUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Object data, String htmlTmp, String path) throws TemplateException, IOException {
        Writer out = new StringWriter();
        try {
            Configuration freemarkerCfg = new Configuration();
            freemarkerCfg.setDirectoryForTemplateLoading(new File(path));
            Template template = freemarkerCfg.getTemplate(htmlTmp, "UTF-8");
            // 合并数据模型与模板 //将合并后的数据和模板写入到流中，这里使用的字符流
            template.process(data, out);
            out.flush();
            return out.toString();
        } catch (Exception e) {
            logger.error("", e);
            throw e;
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                logger.error("", ex);
            }
        }
    }

    public static File getFreeMarkerRenderFile(Object data, String htmlTmp){
        Writer out = null;
        File file = new File(folder+"/"+htmlTmp);
        try {
            File freeMarkerRenderFile = new File("temp"+File.separator+ UUID.randomUUID());
            out = new FileWriter(freeMarkerRenderFile, StandardCharsets.UTF_8);
            // 获取模板,并设置编码方式
            if(file.exists() && file.isFile()){
                Template template = freemarkerCfgOut.getTemplate(htmlTmp, "UTF-8");
                // 合并数据模型与模板
                template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
                logger.info("template is from[{}].", file);
            }else {
                Template template = freemarkerCfg.getTemplate(htmlTmp, "UTF-8");
                // 合并数据模型与模板
                template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
                logger.info("template is from[{}].", pathPrefix+htmlTmp);
            }
            out.flush();
            return freeMarkerRenderFile;
        } catch (Exception e) {
            logger.error("", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                logger.error("", ex);
            }
        }
        return null;
    }

    /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Object data, InputStream input) throws IOException, TemplateException {
        Writer out = new StringWriter();
        Template template = new Template("", new InputStreamReader(input, StandardCharsets.UTF_8), freemarkerCfg, "UTF-8");
        // 合并数据模型与模板
        template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
        out.flush();
        return out.toString();
    }

    /*public static File getFreeMarkerRenderFile(Object data, InputStream input) throws IOException, TemplateException {
        Writer out = null;
        try {
            File freeMarkerRenderFile = new File("temp"+File.separator+UUID.randomUUID());
            out = new FileWriter(freeMarkerRenderFile, StandardCharsets.UTF_8);
            Template template = new Template("", new InputStreamReader(input, StandardCharsets.UTF_8), freemarkerCfg, "UTF-8");
            // 合并数据模型与模板
            template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
            out.flush();
            return freeMarkerRenderFile;
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                logger.error("", ex);
            }
        }
    }*/

    /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Object data, byte[] bytes) throws IOException, TemplateException {
        Writer out = new StringWriter();
        Template template = new Template("", new InputStreamReader(new ByteArrayInputStream(bytes), StandardCharsets.UTF_8), freemarkerCfg, "UTF-8");
        // 合并数据模型与模板
        template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
        out.flush();
        return out.toString();
    }

    public static ByteArrayOutputStream createPdf(String content, String dest) throws IOException, DocumentException {
        File parentFile = new File(dest).getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            parentFile.mkdirs();
        }
        try{
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ITextRenderer renderer = new ITextRenderer();
            ITextFontResolver fontResolver = renderer.getFontResolver();
            //加载所有字体
            fontResolver.addFont("/font/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            fontResolver.addFont("/font/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            fontResolver.addFont("/font/kaiti.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            renderer.setDocumentFromString(content);
            renderer.layout();
            renderer.createPDF(outputStream);
            return outputStream;
        }catch (Exception e) {
            logger.info(content);
            logger.error("生成PDF失败：", e);
        }
        return null;
    }



    public static byte[] createPdf2ByteArray(String content) throws IOException, DocumentException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ITextRenderer renderer = new ITextRenderer();
        ITextFontResolver fontResolver = renderer.getFontResolver();
        for(Resource resource : fonts) {
            fontResolver.addFont("font/"+resource.getFilename(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }
        renderer.setDocumentFromString(content);
        renderer.layout();
        renderer.createPDF(os);
        return os.toByteArray();
    }

    public static File createPdfTempFile(List<File> contentFiles) throws IOException, DocumentException {
        File pdfTempFile = new File("temp"+File.separator+UUID.randomUUID());
        OutputStream os = new FileOutputStream(pdfTempFile);
        ITextRenderer renderer = new ITextRenderer();
        ITextFontResolver fontResolver = renderer.getFontResolver();
        for(Resource resource : fonts) {
            fontResolver.addFont("font/"+resource.getFilename(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }
        for (int i = 0; i < contentFiles.size(); i++) {
            File contentFile = contentFiles.get(i);
            renderer.setDocument(contentFile);
            renderer.layout();
            if (i == 0) {
                renderer.createPDF(os, false);
            } else {
                renderer.writeNextDocument(i);
            }
        }
        renderer.finishPDF();
        return pdfTempFile;
    }

    public static void mergePDF(List<String> fileNames, String dest) {
        /*Document document = null;
        PdfCopy pdfCopy = null;
        PdfReader pdfReader = null;
        try {
            document = new Document(new PdfReader(fileNames.get(0)).getPageSize(1));
            pdfCopy = new PdfCopy(document, new FileOutputStream(dest));
            document.open();

            for (int i = 0, len = fileNames.size(); i < len; i++) {
                pdfReader = new PdfReader(fileNames.get(i));
                int numberOfPages = pdfReader.getNumberOfPages();
                for (int j = 1; j <= numberOfPages; j++) {
                    document.newPage();
                    PdfImportedPage page = pdfCopy.getImportedPage(pdfReader, j);
                    pdfCopy.addPage(page);
                }
            }
        } catch (Exception e) {
            logger.error("PDF合并异常 :", e);
        } finally {
            if (null != document) {
                document.close();
            }
            if (null != pdfReader) {
                pdfReader.close();
            }
            if (null != pdfCopy) {
                pdfCopy.close();
            }
            for (String fileName : fileNames) {
                FileUtil.del(new File(fileName));
            }
        }*/

    }
}

